home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Scene Storm
/
Scene Storm - Volume 1.iso
/
coding
/
c
/
dependantscan
/
source
/
dependantscan.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-11-14
|
18KB
|
371 lines
#define DEF_DEPENDANTSCAN_C
#include <exec/types.h>
#include <exec/memory.h>
#include <utility/tagitem.h>
#include <dos/dosasl.h>
#include <proto/icon.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <stdio.h>
#include <string.h>
#include "ProcessDirectory.h"
#include "DependantScan.h"
#include "RequesterError.h"
char *DPSArgument[DPS_ARG_COUNT]; /* arguments parsed from the command line or our icon */
char DPSParsedPattern[255]; /* the file pattern we are matching */
int FilesOnLine; /* number of files mentioned on the current line */
FILE *OutputStream = NULL; /* the file we are writing to */
/*
char *wrap_files(
char *in_between) what we are putting between files
* Description
This function will continue the make file on the next line if there are too many files on the current line.
*/
char *wrap_files(
char *in_between) /* what we are putting between files */
{
if (FilesOnLine++ == *(LONG *)DPSArgument[DPS_ARG_FILESONLINE]) /* if this is the last file to be printed on this line */
{
if (!strcmp(in_between," ")) /* if we are building the project dependency list */
fprintf(OutputStream,"\\\n"); /* then, this is how to continue the line */
else if (!strcmp(in_between," + ")) /* if we are building the link object list */
fprintf(OutputStream," +\\\n"); /* continue the line this way */
else /* we don't know what we are doing */
fprintf(OutputStream,"%s\\\n",in_between); /* continue the line in a generic way */
in_between = ""; /* put the next file at the beginning of the next line */
FilesOnLine = 1; /* reset the counter */
}
return (in_between); /* tell caller to use this before the next file */
}
/*
int dpscan_pass1(
struct AnchorPath *anchor, file being processed
char *path, the pathname (including trailing slash) that 'fib' resides in
char *in_between) what to put between each file
* Description
This function is used to build the project dependancy list and link object file list. It is designed to be called by
process_directory(). The only difference in these two parts is what is placed between each file. The 'in_between' argument is used for
this purpose.
Note: This routine uses FilesOnLine and therefore, that value must be properly setup before this routine is called.
*/
int dpscan_pass1(
struct AnchorPath *anchor, /* file being processed */
char *in_between) /* what to put between each file */
{
if (MatchPatternNoCase(DPSParsedPattern,anchor->ap_Info.fib_FileName)) /* if this filename matches */
{
in_between = wrap_files(in_between); /* possibly move to the next line */
if (strrchr(anchor->ap_Info.fib_FileName,'.')) /* if the filename has an extension */
{
*strrchr(anchor->ap_Info.fib_FileName,'.') = '\0'; /* chop off the name at it's extension */
fprintf(OutputStream,"%s$(obj)%s.o",in_between,anchor->ap_Info.fib_FileName); /* put the current file into the make file */
anchor->ap_Info.fib_FileName[strlen(anchor->ap_Info.fib_FileName)] = '.'; /* restore the file's extension */
}
else /* the filename has no extension */
{
fprintf(OutputStream,"%s$(obj)%s.o",in_between,anchor->ap_Info.fib_FileName); /* use the filename as-is */
}
}
if (*in_between && DPSArgument[DPS_ARG_VERBOSE]) /* if we should print stuff */
printf(dps_locale_string(DPS_MSG_PASS1_PROGRESS));
return (0);
}
/*
int dpscan_pass2(
struct AnchorPath *anchor, file being processed
void *_not_used) currently unused argument
* Description
This routine is designed to be called by process_directory(). It builds the dependancy list for the source modules in the make file.
This function assumes that DPSParsedPattern has been created.
*/
int dpscan_pass2(
struct AnchorPath *anchor, /* file being processed */
void *_not_used) /* currently unused argument */
{
FILE *input_stream = NULL; /* connected to the file we are scanning for dependants */
char temp_str[DPS_LINE_BUFFER_SIZE]; /* for buffering lines of the #include file */
char *include_name; /* points to the file being included (a portion of 'temp_str') */
int retval = 0; /* 0 = good, other = bad */
if (MatchPatternNoCase(DPSParsedPattern,anchor->ap_Info.fib_FileName) == FALSE) /* if this filename does not match */
goto _ABORT;
fprintf(OutputStream,"\n\n"); /* setup for the new target */
FilesOnLine = 0; /* setup for call to dpscan_pass1() */
dpscan_pass1(anchor,""); /* put the object file for this bit of source code at the start of the line */
fprintf(OutputStream,": %s",anchor->ap_Buf); /* put the file itself as a dependant into the makefile */
if (DPSArgument[DPS_ARG_VERBOSE]) /* if we should print stuff */
printf(dps_locale_string(DPS_MSG_PASS2_FILE),anchor->ap_Buf); /* show user which file we are processing what is happening */
if ((input_stream = fopen(anchor->ap_Info.fib_FileName,"r")) == NULL) /* if we cannot open the file */
{
quick_requester_error(retval = DPS_ERROR_CANNOT_OPEN_FILE,DPS_ERROR_CANNOT_OPEN_FILE,anchor->ap_Info.fib_FileName);
goto _ABORT;
}
while (fgets(temp_str,sizeof(temp_str),input_stream)) /* while we can get a line from the file */
{
if ((include_name = strstr(temp_str,"#include")) != NULL) /* if this line includes something */
{
if ((include_name = strchr(include_name,'\"')) != NULL) /* if it is the type of #include that has quotes */
{
++include_name; /* skip the opening quote */
if (strchr(include_name,'\"')) /* if there is a second quote on this line */
{
*strchr(include_name,'\"') = '\0'; /* cut off the name at the second quote */
fprintf(OutputStream,"%s",wrap_files(" ")); /* separate this file from previous ones */
/* put the path of this #include file into the makefile */
if (strrchr(anchor->ap_Buf,'/')) /* if the full name has a slash in it */
fprintf(OutputStream,"%.*s",1 + (strrchr(anchor->ap_Buf,'/') - anchor->ap_Buf), anchor->ap_Buf);
else if (strrchr(anchor->ap_Buf,':')) /* if the full name has a drive in it */
fprintf(OutputStream,"%.*s",1 + (strrchr(anchor->ap_Buf,':') - anchor->ap_Buf), anchor->ap_Buf);
fprintf(OutputStream,"%s",include_name); /* put the #include file into the makefile */
if (DPSArgument[DPS_ARG_VERBOSE]) /* if we should print stuff */
printf(dps_locale_string(DPS_MSG_PASS2_PROGRESS)); /* show user what is happening */
}
}
}
else if (strchr(temp_str,'{')) /* if this line is after the #include's */
{
break; /* then, we are finished */
}
}
if (strrchr(anchor->ap_Info.fib_FileName,'.')) /* if the filename has a period in it */
fprintf(OutputStream,"\n\t$(CC) $*%s",strrchr(anchor->ap_Info.fib_FileName,'.')); /* tell the compiler how to compile this project */
else /* no period in the file name */
fprintf(OutputStream,"\n\t$(CC) $*"); /* use default compilation???? */
if (DPSArgument[DPS_ARG_VERBOSE]) /* if we should print stuff */
printf(dps_locale_string(DPS_MSG_PASS2_SEPARATOR)); /* show user what is happening */
_ABORT:
if (input_stream) /* if we have a file open */
fclose(input_stream); /* then, clean up after ourselves */
return (retval);
}
/*
int dps_build_path(
char *destination, the resulting pathname may be stored here
char *source) the source pathname
* Description
If possible, this function will combine DPSArgument[DPS_ARG_PATH] with 'source' and store the result at 'destination'.
* Return Value
0 = could not combine the paths
1 = paths combined
*/
int dps_build_path(
char *destination, /* the resulting pathname may be stored here */
char *source) /* the source pathname */
{
char last_char; /* the last character in 'source' */
if (!strchr(source,':') && (source[0] != '/')) /* if the source pathname does not have a directory specifier in it */
{
strcpy(destination,DPSArgument[DPS_ARG_PATH]); /* start with the path for our operations */
last_char = destination[strlen(destination)-1]; /* get the last character for examination */
if ((last_char != ':') && (last_char != '/')) /* if a directory separator is needed */
strcat(destination,"/"); /* put the directory separator */
strcat(destination,source); /* create the remainder of the path */
return (1); /* let caller know that we could do it */
}
return (0); /* we didn't do it */
}
/*
int dps_include_rules(
char *filename) the name of the rules file to be included
* Description
This function attempts to write the file specified by 'filename' to OutputStream (the makefile).
* Return Value
0 = OK
other = bad
*/
int dps_include_rules(
char *filename) /* the name of the rules file to be included */
{
int retval = 0; /* another value is bad */
FILE *stream; /* connected to the rules file */
char *line_buffer = NULL; /* for buffering the input file */
size_t bytes_read; /* the number of bytes read on each pass */
if (DPSArgument[DPS_ARG_VERBOSE]) /* if we should say what is happening */
printf(dps_locale_string(DPS_MSG_INCLUDING_RULES),filename);
if ((stream = fopen(filename,"r")) == NULL) /* if we cannot open the file */
/* then, we are done */
{quick_requester_error(retval = DPS_ERROR_CANNOT_OPEN_FILE,DPS_ERROR_CANNOT_OPEN_FILE,filename); goto _ABORT;}
if ((line_buffer = AllocVec(DPS_LINE_BUFFER_SIZE,0)) == NULL) /* if we cannot get some memory for our buffer */
{quick_requester_error(retval = DPS_ERROR_CANNOT_ALLOCATE,DPS_ERROR_CANNOT_ALLOCATE,DPS_LINE_BUFFER_SIZE); goto _ABORT;}
while (!feof(stream) && !ferror(stream)) /* while we are not at the end of the file and there is no error with the file */
{
if ((bytes_read = fread(line_buffer,1,DPS_LINE_BUFFER_SIZE,stream)) == 0) /* if we have no more bytes to read */
break;
if (fwrite(line_buffer,1,bytes_read,OutputStream) != bytes_read) /* if we cannot write some bytes */
{quick_requester_error(retval = DPS_ERROR_CANNOT_WRITE_FILE,DPS_ERROR_CANNOT_WRITE_FILE,bytes_read,filename); goto _ABORT;}
}
_ABORT:
if (stream) /* if we have a file open */
fclose(stream); /* clean up after ourselves */
return (retval); /* non-zero is bad */
}
/*
int dependant_scan(void)
* Description
This function makes a makefile with the currently parsed arguments (mostly).
*/
int dependant_scan(void)
{
char object_dir_path[PD_PATHMAX]; /* if needed, the new value for DPSArgument[DPS_ARG_OBJECT_DIR] */
int retval = 0; /* other than this value is bad */
if (DPSArgument[DPS_ARG_PATH]) /* if we are scanning a different directory */
{
if (dps_build_path(object_dir_path,DPSArgument[DPS_ARG_OBJECT_DIR])) /* if the object directory can be expanded */
DPSArgument[DPS_ARG_OBJECT_DIR] = object_dir_path; /* then, use the fully-qualified path */
}
if (DPSArgument[DPS_ARG_VERBOSE]) /* if we should say what is happening */
printf(dps_locale_string(DPS_MSG_CREATING_SMAKEFILE),DPSArgument[DPS_ARG_MAKEFILE]);
if ((OutputStream = fopen(DPSArgument[DPS_ARG_MAKEFILE],"w")) == NULL) /* if we cannot open the output file */
{quick_requester_error(retval = DPS_ERROR_CANNOT_OPEN_FILE,DPS_ERROR_CANNOT_OPEN_FILE,DPSArgument[DPS_ARG_MAKEFILE]); goto _ABORT;}
if (DPSArgument[DPS_ARG_RULES]) /* if we should include a "rules" file at the top of the makefile */
{
if ((retval = dps_include_rules(DPSArgument[DPS_ARG_RULES])) != 0) /* if we have difficulty including the rules file */
goto _ABORT;
}
ParsePatternNoCase(DPSArgument[DPS_ARG_MATCH],DPSParsedPattern,sizeof(DPSParsedPattern)); /* convert the file pattern into something useful */
/* create the first part of the first couple of lines */
fprintf(OutputStream,"obj = %s\n\n%s:",DPSArgument[DPS_ARG_OBJECT_DIR],DPSArgument[DPS_ARG_PROJECT]);
FilesOnLine = 1; /* only one file on this line */
if (DPSArgument[DPS_ARG_VERBOSE]) /* if we should print stuff */
printf(dps_locale_string(DPS_MSG_PASS1_BEGINNING));
/* if we cannot perform the first pass */
if (process_directory(DPSArgument[DPS_ARG_PATH],"#?",dpscan_pass1,process_directory_do_nothing," "))
{quick_requester_error(retval = DPS_ERROR_PASS_UNSUCCESSFUL,DPS_ERROR_PASS_UNSUCCESSFUL,1); goto _ABORT;}
fprintf(OutputStream,"\n\t$(LD) <WITH <\nFrom %s",DPSArgument[DPS_ARG_FROM]); /* setup the link part */
FilesOnLine = 1; /* only one file on this line */
if (DPSArgument[DPS_ARG_VERBOSE]) /* if we should print stuff */
printf(dps_locale_string(DPS_MSG_BUILDING_LINK_LIST));
/* if we cannot perform the second pass */
if (process_directory(DPSArgument[DPS_ARG_PATH],"#?",dpscan_pass1,process_directory_do_nothing," + "))
{quick_requester_error(retval = DPS_ERROR_PASS_UNSUCCESSFUL,DPS_ERROR_PASS_UNSUCCESSFUL,2); goto _ABORT;}
if (DPSArgument[DPS_ARG_VERBOSE]) /* if we are printing stuff */
printf(dps_locale_string(DPS_MSG_PASS2_BEGINNING));
fprintf(OutputStream,"\n\nTo %s\nLibrary %s\n<",DPSArgument[DPS_ARG_PROJECT],DPSArgument[DPS_ARG_LIBRARY]);
if (process_directory(DPSArgument[DPS_ARG_PATH],"#?",dpscan_pass2,process_directory_do_nothing,NULL))
{quick_requester_error(retval = DPS_ERROR_PASS_UNSUCCESSFUL,DPS_ERROR_PASS_UNSUCCESSFUL,3); goto _ABORT;}
_ABORT:
if (OutputStream) /* if we have a file open */
{
if (DPSArgument[DPS_ARG_VERBOSE]) /* if we should say what is happening */
printf(dps_locale_string(DPS_MSG_CLOSING_SMAKEFILE),DPSArgument[DPS_ARG_MAKEFILE]);
fclose(OutputStream); /* then, close it */
OutputStream = NULL; /* note that it is closed */
}
return (retval); /* let caller know what happened */
}
int main(
int argc,
char *argv)
{
struct RDArgs *rdargs = NULL; /* for parsing the command line */
BOOL free_args_needed = FALSE; /* true when we should call FreeArgs() */
int retval = 0;
requester_error_set_defaults(NULL,dps_locale_string(DPS_MSG_DEPENDANTSCAN_ERROR),dps_locale_string,dps_locale_string(DPS_MSG_DARN));
if (argc) /* if we were started from the shell */
{
if ((rdargs = (struct RDArgs *)AllocDosObject(DOS_RDARGS,TAG_DONE)) == NULL) /* if we cannot get some memory for this DOS structure */
{quick_requester_error(retval = DPS_ERROR_ALLOCDOSOBJECT,DPS_ERROR_ALLOCDOSOBJECT); goto _ABORT;}
if ((free_args_needed = dps_get_shell_arguments(rdargs)) == FALSE) /* if we have an error while getting the command line arguments */
{
PrintFault(IoErr(),dps_locale_string(DPS_MSG_DEPENDANTSCAN)); /* tell the user what went wrong */
retval = DPS_ERROR_PASS_UNSUCCESSFUL;
goto _ABORT;
}
retval = dependant_scan(); /* actually do the scanning */
}
else /* must have been started from the WB */
{
retval = dps_process_workbench_arguments((struct WBStartup *)argv); /* parse the workbench arguments */
}
_ABORT:
if (retval == 0) /* if this was a successful run */
{
if (DPSArgument[DPS_ARG_VERBOSE]) /* if we are notifying the user */
/* notify the user of the successful run */
requester_error(NULL,dps_locale_string(DPS_MSG_DEPENDANTSCAN_MSG),NULL,dps_locale_string(DPS_MSG_COOL),DPS_MSG_SUCCESSFUL,DPSArgument[DPS_ARG_MAKEFILE],DPSArgument[DPS_ARG_PROJECT]);
}
if (free_args_needed) /* if we need to free any arguments allocated by DOS */
FreeArgs(rdargs); /* then, we don't need them anymore */
if (rdargs) /* if we allocated this */
FreeDosObject(DOS_RDARGS,rdargs); /* then, free it */
return (retval);
}